#import <SpringBoard/SBApplication.h>
#import <SpringBoard/SBApplicationController.h>
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#import <UIKit/UIApplication.h>
#import <LockInfo/Plugin.h>

#import "framework/FWCommon.h"
#import "framework/FWApplication.h"
#import "framework/FWIconDotView.h"
#import "framework/FWDotView.h"
#import "framework/FWColorIconView.h"
#import "framework/FWRoundedLabel.h"
#import "framework/FWStrikeoutView.h"

#import "PIEventView.h"
#import "PIEventPlugin.h"
#import "PIIntegration.h"


static CGRect const kMarkerRect = CGRectMake(0, 0, kFWListViewMarkerSize, kFWListViewMarkerSize);
static NSInteger const kStrikethrough = 12345;


@implementation PIEventView

@synthesize repeat, availability, attendees, reminder, startTime, endTime, timeSummary, alarm, combineHighlight, native;


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

- (id)initWithFrame:(CGRect)frame theme:(LITheme*)theme application:(FWApplication*)appl;
{
    if ((self = [super initWithFrame:frame theme:theme])) {
        self.largestIcon = kFWListViewMarkerSize;
        self.abbreviateDetail = YES;

        self.startTime = FWLILabel(CGRectZero);
        self.startTime.frame = CGRectZero;
        self.startTime.autoresizingMask = UIViewAutoresizingNone;
        self.startTime.backgroundColor = [UIColor clearColor];

        self.endTime = FWLILabel(CGRectZero);
        self.endTime.frame = CGRectZero;
        self.endTime.autoresizingMask = UIViewAutoresizingNone;
        self.endTime.backgroundColor = [UIColor clearColor];

        self.availability = [[[FWColorIconView alloc] initWithFrame:kMarkerRect] autorelease];
        self.availability.backgroundColor = [UIColor clearColor];
        
        self.repeat = [[[FWColorIconView alloc] initWithFrame:kMarkerRect] autorelease];
        self.repeat.icon = [PIIntegration iconPathForRepeat:appl];
        
        self.attendees = [[[FWColorIconView alloc] initWithFrame:kMarkerRect] autorelease];
        self.attendees.icon = [PIIntegration iconPathForAttendees:appl];
        
        self.reminder = [[[FWColorIconView alloc] initWithFrame:kMarkerRect] autorelease];
        self.reminder.icon = [PIIntegration iconPathForReminder:appl];

        self.native = [[[FWColorIconView alloc] initWithFrame:kMarkerRect] autorelease];
        //self.native.icon = [appl.pluginBundle pathForResource:@"native" ofType:@"png"];

        NSString* reminderIconPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"alarm" ofType:@"png"];
        self.alarm = [[[FWColorIconView alloc] initWithFrame:CGRectMake(0, 0, 14, 14)] autorelease];
        self.alarm.icon = reminderIconPath;
        self.alarm.color = [UIColor redColor];

        [self addSubview:self.native];
        [self addSubview:self.repeat];
        [self addSubview:self.availability];
        [self addSubview:self.attendees];
        [self addSubview:self.reminder];
        [self addSubview:self.startTime];
        [self addSubview:self.endTime];
        [self addSubview:self.alarm];
        
        self.flags = [NSArray arrayWithObjects:
                      self.native,
                      self.repeat,
                      self.attendees,
                      self.availability,
                      self.reminder,
                      nil];
    }
    
    return self;
}

-(void)dealloc 
{
    [native release];
    [availability release];
    [repeat release];
    [attendees release];
    [reminder release];
    [startTime release];
    [endTime release];
    [timeSummary release];
    [alarm release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Updating and presenting information to the user

- (void)setViewForEvent:(PIEvent *)event theme:(LITheme*)theme application:(FWApplication*)app style:(kPIEventViewStyle)style showDetail:(ShowDatesOptions)showDetails showCalendar:(BOOL)calendar showDate:(BOOL)showDate showAvailability:(BOOL)showAvail lowColour:(BOOL)lowColour sourceIcon:(ShowSourceIconOptions)sourceIcon
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    
    // Looks poor otherwise!
    if ((style == kPIEventViewStyleTraditional) && (showDetails == ShowDatesAlways))
        showDetails = ShowDatesIfNeeded;

    viewStyle = style;
    self.drawBorder = event.isInvitation;
    
    NSString* startText = event.isAllDay ? nil : FWLocalDateStringForUTCDate(event.startDate, showDate ? FWDateFormatterLongAbbreviatedFormat : FWDateFormatterTimeOnlyFormat, YES, bundle);
    NSString* endText = event.isAllDay ? nil : FWLocalDateStringForUTCDate(event.endDate, FWDateFormatterTimeOnlyFormat, YES, bundle);
    
    if (app.fwPlugin.isDebugMode) {
        if (event.isAllDay)
            startText = [startText stringByAppendingString:@"d"];
        if (![event.nextAlarm isNull])
            startText = [startText stringByAppendingString:@"n"];
    }
    
    // Add the title
    pastEvent = !event.isAllDay && [[NSDate date] isLaterThanDate:event.endDate];
    self.summaryText.style = theme.summaryStyle;
    self.summaryText.text = [PIIntegration stringForTitle:event.title withIcon:event.icon withProjectIcon:event.calendarIcon];
    [self.summaryText setNeedsDisplay];
    
    if (FWStrikeoutView* strikethrough = (FWStrikeoutView*)[self.summaryText viewWithTag:kStrikethrough]) {
        if (!pastEvent)
            [strikethrough removeFromSuperview];
        else
            strikethrough.strikeoutColor = self.summaryText.style.textColor;
    }
    else {
        if (pastEvent) {
            FWStrikeoutView* strikethrough = [[[FWStrikeoutView alloc] initWithFrame:CGRectZero] autorelease];
            strikethrough.tag = kStrikethrough;
            strikethrough.strikeoutColor = self.summaryText.style.textColor;
            [self.summaryText addSubview:strikethrough];
        }
    }
    
    // Add the time
    if (style == kPIEventViewStyleTraditional) {
        self.startTime.hidden = NO;
        self.startTime.style = [[theme.summaryStyle copy] autorelease];
            
        if (!event.isAllDay) {
            self.startTime.text = startText;
            [self.startTime setNeedsDisplay];
            
            if ((event.hasDetails || calendar) && ![event.startDate isEqualToDate:event.endDate]) {
                self.endTime.hidden = NO;
                self.endTime.text = [NSString stringWithFormat:@"-%@", endText];
                self.endTime.style = [[theme.summaryStyle copy] autorelease];
                [self.endTime setNeedsDisplay];
            }
            else
                self.endTime.hidden = YES;
        }
        else {
            self.startTime.text = localize(bundle, @"Detail/All Day");;
            self.endTime.hidden = YES;
            [self.startTime setNeedsDisplay];
        }
        
        if (calendar) {
            combineHighlight = NO;
            self.highlightText.label.text = event.calendar;
            self.highlightText.hidden = NO;
        }
        else
            self.highlightText.hidden = YES;
    }
    else {
        self.startTime.hidden = self.endTime.hidden = YES;
        self.highlightText.hidden = NO;
        
        if (event.isAllDay) {
            if (showDate)
                startText = [NSString stringWithFormat:@"%@ %@",
                             FWLocalDateStringForUTCDate(event.startDate, FWDateFormatterLongAbbreviatedFormat, NO, bundle),
                             localize(bundle, @"Detail/All Day")];
            else
                startText = localize(bundle, @"Detail/All Day");
        }
        else if (![event.startDate isEqualToDate:event.endDate])
            startText = [startText stringByAppendingFormat:@"\u2014%@", endText];
        
        if (calendar) {
            combineHighlight = NO;
            if (viewStyle == kPIEventViewStyleTimeAtEnd)
                self.highlightText.label.text = [NSString stringWithFormat:@"(%@)  %@", event.calendar, startText];
            else
                self.highlightText.label.text = [startText stringByAppendingFormat:@"  (%@)", event.calendar];
        }
        else {
            combineHighlight = YES;
            self.highlightText.label.text = startText;
        }
    }
    

    if (!self.highlightText.isHidden) {
        self.highlightText.label.font = theme.detailStyle.font;
        
        if (lowColour) {
            [self.highlightText setRoundedColor:theme.detailStyle.textColor];
            self.highlightText.textColor = FWIsColorDark(theme.detailStyle.textColor) ? [UIColor whiteColor] : [UIColor blackColor];
        }
        else {
            [self.highlightText setRoundedColor:event.calendarColor];
            self.highlightText.textColor = FWIsColorDark(event.calendarColor) ? [UIColor whiteColor] : [UIColor blackColor];
        }
        
        [self.highlightText setNeedsDisplay];
    }


    // Add the section header if there is one
    if (event.sectionTitle && (event.sectionTitle.length > 0)) {
        [self addHeader:theme];
        
        self.headerText.text = event.sectionTitle;
        self.headerText.style = theme.summaryStyle;
        [self.headerText setNeedsDisplay];

        if (event.sectionDetails) {
            self.timeSummary.hidden = NO;
            //self.timeSummary.roundedColor = [UIColor darkGrayColor];
            self.timeSummary.legendColor = theme.summaryStyle.textColor;

            self.timeSummary.timeIntervals = event.sectionDetails;
            self.timeSummary.start = event.sectionStartInterval;
            self.timeSummary.duration = event.sectionEndInterval - event.sectionStartInterval;
            
            self.timeSummary.legendColor = [UIColor whiteColor];
            self.timeSummary.borderColor = theme.summaryStyle.textColor;
            self.timeSummary.scaleColor = [UIColor clearColor];
            self.timeSummary.currentDay = FWIsLocalDateToday(event.startDate);
            
            [self.timeSummary setNeedsDisplay];
        }
        else {
            self.timeSummary.hidden = YES;
            self.timeSummary.timeIntervals = nil;
        }
    }
    else
        [self removeHeader];
    
    
    // Add the availability icon if there is one
    NSString* availIcon = nil;
//    UIColor* availColor = [UIColor clearColor];
    switch (event.availability) {
        case kPIEventAvailabilityBusy:
            availIcon = @"busy";
//            availColor = [PIIntegration colorBGForImportance:PIImportanceNormal application:app];
            break;
        case kPIEventAvailabilityTentative:
            availIcon = @"tentative";
//            availColor = [PIIntegration colorBGForImportance:PIImportanceLow application:app];
            break;
        case kPIEventAvailabilityUnavailable:
            availIcon = @"unavailable";
//            availColor = [PIIntegration colorBGForImportance:PIImportanceHigh application:app];
            break;
        case kPIEventAvailabilityOutOfOffice:
            availIcon = @"outofoffice";
//            availColor = [PIIntegration colorBGForImportance:PIImportanceTop application:app];
            break;
        default:
            break;
    }

    if (showAvail && availIcon && !self.drawBorder) {
        self.availability.hidden = NO;
        self.availability.color = theme.summaryStyle.textColor; //availColor;
        self.availability.icon = [bundle pathForResource:availIcon ofType:@"png"];
    }
    else
        self.availability.hidden = YES;


    // Add the location if we have one
    self.detailText.style = theme.detailStyle;
    if (event.location && (event.location.length > 0)) {
        combineHighlight = NO;
        self.detailText.hidden = NO;
        self.detailText.text = event.location;
    }
    else
        self.detailText.hidden = YES;


    // Have we overridden the show details option?
    if (!self.detailText.isHidden) {
        if (showDetails == ShowDatesNever) {
            combineHighlight = YES;
            self.detailText.hidden = YES;
        }
        else if (showDetails == ShowDatesAlways)
            combineHighlight = NO;
    }    

    self.dot.color = event.calendarColor;
    [self.dot setNeedsDisplay];
    
    if (event.isRepeating) {
        self.repeat.hidden = NO;
        self.repeat.color = self.summaryText.style.textColor;
    }
    else
        self.repeat.hidden = YES;

    if (![event.firstAlarm isNull]) {
        self.reminder.hidden = NO;
        self.reminder.color = self.summaryText.style.textColor;
    }
    else
        self.reminder.hidden = YES;

    if (event.hasAttendees) {
        self.attendees.hidden = NO;
        self.attendees.color = self.summaryText.style.textColor;
    }
    else
        self.attendees.hidden = YES;

    if (event.isReminderInteract) {
        self.alarm.hidden = NO;
        self.alarm.color = self.summaryText.style.textColor;
    }
    else
        self.alarm.hidden = YES;

    if (event.isNative && ((sourceIcon == ShowSourceIconOptionsBoth) || (sourceIcon == ShowSourceIconOptionsIOSOnly))) {
        self.native.icon = [bundle pathForResource:@"native" ofType:@"png"];
        self.native.hidden = NO;
    }
    else if (!event.isNative && ((sourceIcon == ShowSourceIconOptionsBoth) || (sourceIcon == ShowSourceIconOptionsPIOnly))) {
        self.native.icon = [bundle pathForResource:@"pi" ofType:@"png"];
        self.native.hidden = NO;
    }
    else
        self.native.hidden = YES;

    if (!self.native.isHidden)
        self.native.color = self.summaryText.style.textColor;

    //self.singleLine = self.highlightText.hidden && self.detailText.hidden;

    [self setNeedsLayout];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Layout support

static const CGFloat kSummaryStartProportion = 0.5;
static const CGFloat kSummaryWidth = 150;

- (void)layoutSubviews
{
    if (viewStyle ==  kPIEventViewStyleTraditional) {
        // Get local version of the midnight string for sizing the time field
        NSDateFormatter* tf = [[NSDateFormatter alloc] init];
        tf.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
        tf.dateStyle = NSDateFormatterNoStyle;
        tf.timeStyle = NSDateFormatterShortStyle;
        NSString* reference = [[tf stringFromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:0]] stringByAppendingString:@"-"];
        [tf release];
        
        CGSize size = [reference sizeWithFont:self.summaryText.style.font];
        self.leftReservedSpace = size.width + kFWListViewSeparatorSize * 2;

#ifdef DEVELOPMENT_MODE
        startTime.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.3];
        endTime.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.3];
#endif
    }
    else
        self.leftReservedSpace = 0;
    
    [super layoutSubviews];
    
    // Layout the time summary in the header if necessary
    if (!self.timeSummary.hidden) {
        CGRect summaryRect = self.headerBackground.frame;
        summaryRect.origin.x = summaryRect.size.width - kSummaryWidth - kFWListViewSeparatorSize;
        summaryRect.origin.y += 1;
        summaryRect.size.width = kSummaryWidth;
        //summaryRect.size.height -= 2;
        summaryRect.size.height -= 1;

        self.timeSummary.frame = summaryRect;
        [self.timeSummary setNeedsDisplay];
    }
    
    
    // Center the time values
    if (viewStyle == kPIEventViewStyleTraditional) {
        CGRect rowRect = self.summaryText.frame;
        if (!self.detailText.isHidden || !self.highlightText.isHidden)
            rowRect.size.height += self.detailText.frame.size.height;
        CGRect timeRect = startTime.frame;
        if (!endTime.isHidden)
            timeRect.size.height = CGRectGetMaxY(endTime.frame) - CGRectGetMinY(timeRect);
        
        CGFloat offset = (rowRect.size.height - timeRect.size.height) / 2;
        
        CGRect startFrame = startTime.frame;
        startFrame.origin.y += offset;
        startTime.frame = startFrame;
    }
    
    
    // Do we need to move the highlight view? This will be a lot of work!
    if (!self.highlightText.isHidden) {
        if ((viewStyle == kPIEventViewStyleTimeAtStart) && combineHighlight) {
            // Do nothing special if the time is at the start unless we are combining with
            // the first line
            CGRect highlightRect = self.highlightText.frame;
            CGRect summaryRect = self.summaryText.frame;
            CGFloat space = highlightRect.size.width + 2 * kFWListViewSeparatorSize;
            
            highlightRect.origin.y = summaryRect.origin.y + (summaryRect.size.height - highlightRect.size.height) / 2;
            summaryRect.origin.x += space;
            summaryRect.size.width -= space;
            
            self.summaryText.frame = summaryRect;
            self.highlightText.frame = highlightRect;
        }
        else if (viewStyle == kPIEventViewStyleTimeAtEnd) {
            CGRect highlightRect = self.highlightText.frame;
            CGRect summaryRect = self.summaryText.frame;
            CGRect detailRect = self.detailText.frame;
            
            if (highlightRect.origin.x <= summaryRect.origin.x) {
                if (combineHighlight) {
                    CGFloat space = highlightRect.size.width + kFWListViewSeparatorSize * 2;
                    CGFloat rightMost = self.summaryText.frame.origin.x + self.summaryText.frame.size.width;
                    
                    summaryRect.size.width -= space;
                    self.summaryText.frame = summaryRect;
                    
                    for (UIView* flags in self.flags) {
                        if (!flags.isHidden) {
                            CGRect flagFrame = flags.frame;
                            CGFloat right = flagFrame.origin.x + flagFrame.size.width;
                            if (rightMost < right)
                                rightMost = right;
                            flagFrame.origin.x -= space;
                            flags.frame = flagFrame;
                        }
                    }
                    
                    highlightRect.origin.y = summaryRect.origin.y + (summaryRect.size.height - highlightRect.size.height) / 2;
                    highlightRect.origin.x = rightMost - highlightRect.size.width;
                    self.highlightText.frame = highlightRect;
                }
                else {
                    // Move to the end of the detail line
                    detailRect.origin.x = highlightRect.origin.x;
                    highlightRect.origin.x += detailRect.size.width + kFWListViewSeparatorSize;
                    
                    self.highlightText.frame = highlightRect;
                    self.detailText.frame = detailRect;
                }
            }
        }
    
        if (combineHighlight && !self.dot.hidden) {
            // Place the dot half way up the title line
            CGRect dotRect = self.dot.frame;
            CGFloat pos = (self.summaryText.frame.size.height - dotRect.size.height) / 2;
            
            self.dot.frame = CGRectMake(dotRect.origin.x,
                                        self.summaryText.frame.origin.y + pos,
                                        dotRect.size.width,
                                        dotRect.size.height);
        }
    }
    
    if (pastEvent) {
        if (UIView* view = [self.summaryText viewWithTag:kStrikethrough]) {
            CGRect frame = self.summaryText.frame;
            frame.origin.x = frame.origin.y = 0;
            frame.size.width = [self.summaryText.text sizeWithFont:self.summaryText.style.font].width;

            if (frame.size.width > self.summaryText.frame.size.width)
                frame.size.width = self.summaryText.frame.size.width;
            
            frame = CGRectInset(frame, -2, 3);
            [view setFrame:frame];
            [self.summaryText bringSubviewToFront:view];
        }
    }
}

- (void)layoutSummaryRow:(CGRect)rect
{
    [super layoutSummaryRow:rect];

    if (viewStyle ==  kPIEventViewStyleTraditional) {
        CGRect timeRect = CGRectMake(rect.origin.x + kFWListViewDetailMargin,
                                     rect.origin.y,
                                     self.leftReservedSpace - kFWListViewSeparatorSize,
                                     rect.size.height);

        UIFont* font = self.summaryText.style.font;
        if (startTime.text.length > 0) {
            CGFloat minFontSize = font.pointSize / 2;
            do {
                CGSize size = [self.startTime.text sizeWithFont:font];
                if (size.width <= timeRect.size.width)
                    break;
                font = [font fontWithSize:font.pointSize - 2];
            }
            while (font.pointSize > minFontSize);
        }
        timeRect.size.height = font.leading;
        self.startTime.frame = timeRect;
        self.startTime.style.font = font;
        
        if (!self.endTime.isHidden) {
            timeRect.origin.y += timeRect.size.height + self.startTime.style.font.descender;
            self.endTime.frame = timeRect;

            // LILabel seems to stretch its text on rotation unless we do this
            [self.endTime setNeedsDisplay];
        }
        
        // LILabel seems to stretch its text on rotation unless we do this
        [self.startTime setNeedsDisplay];
    }
    
    // Show the alarm symbol just before the summary text
    if (!self.alarm.isHidden) {
        CGRect summaryRect = self.summaryText.frame;
        
        CGRect alarmRect = self.alarm.frame;
        alarmRect.origin.x = summaryRect.origin.x;
        alarmRect.origin.y = summaryRect.origin.y + (summaryRect.size.height - alarmRect.size.height) / 2;
        self.alarm.frame = alarmRect;
        
        summaryRect.origin.x += self.alarm.frame.size.width + kFWListViewSeparatorSize;
        summaryRect.size.width -= self.alarm.frame.size.width + kFWListViewSeparatorSize;
        self.summaryText.frame = summaryRect;
    }
}

- (void)addHeader:(LITheme*)theme
{
    [super addHeader:theme];
    
    if (!self.timeSummary) {
        self.timeSummary = [[[PIEventTimeSummary alloc] initWithFrame:CGRectZero] autorelease];
        self.timeSummary.autoresizingMask = UIViewAutoresizingNone;
        self.timeSummary.backgroundColor = [UIColor clearColor];
        [self addSubview:self.timeSummary];
    }
}

- (void)removeHeader
{
    [super removeHeader];
    
    if (self.timeSummary) {
        [self.timeSummary removeFromSuperview];
        self.timeSummary = nil;
    }
}


// ******************************************************************************************
#pragma mark -
#pragma mark Row height support

+ (CGFloat)heightOfSummaryRowWithFont:(UIFont*)font withHeader:(BOOL)header withFollowingRow:(BOOL)following
{
    CGFloat height = [FWListView heightOfSummaryRowWithFont:font withHeader:header withFollowingRow:following];
    
//    // If no following line and the text area is smaller than the marker, use the marker size
//    if (!following) {
//        CGFloat minHeight = kFWListViewMarkerSpace + (header ? font.leading : 0);
//        if (height <= minHeight)
//            height = minHeight + 1;
//    }
    
    return height;
}

@end
